﻿
using Newtonsoft.Json;
using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Yoze.Common;
using Yoze.Common.Events;
using Yoze.Common.Messaging;
using Yoze.Common.Repositories;
using Yoze.Redis.Common;

namespace Yoze.DomainRepositories
{
    public class RedisDomainRepository : DomainRepository
    {
        private readonly RedisSetting setting;

        private readonly PooledRedisClientManager redisManager;

        private readonly Lazy<IRedisClient> database;

        public RedisDomainRepository(RedisSetting setting, IMessagePublisher bus) : base(bus)
        {
            this.setting = setting;
            this.redisManager = PoolManagerFactory.CreateManager(
                                                                                       new[] { setting.ConnectionString },
                                                                                       new[] { setting.ConnectionString }
                                                                                       , 0);
            this.database = new Lazy<IRedisClient>(() => redisManager.GetClient());
        }

        private async Task<TAggregateRoot> GetAggregateAsync<TKey, TAggregateRoot>(Func<TAggregateRoot, bool> filter)
            where TKey : IEquatable<TKey>
            where TAggregateRoot : IAggregateRoot<TKey>
        {
            var item = database.Value.As<TAggregateRoot>().GetAll().Where(filter).FirstOrDefault();

            return await Task.FromResult(item);
        }


        protected override async Task<TAggregateRoot> GetAggregateAsync<TKey, TAggregateRoot>(TKey aggregateRootKey)
        {
            Func<TAggregateRoot, bool> filter = itm => itm.Id.Equals(aggregateRootKey);
            return await GetAggregateAsync<TKey, TAggregateRoot>(filter);
        }


        protected override async Task SaveAggregateAsync<TKey, TAggregateRoot>(TAggregateRoot aggregateRoot)
        {
            Func<dynamic, bool> filter = item => item.Id.Equals(aggregateRoot.Id);
            var saved = await GetAggregateAsync<TKey, TAggregateRoot>(filter);
            if (saved != null)
            {
                database.Value.As<TAggregateRoot>().Delete(saved);
                database.Value.As<TAggregateRoot>().Store(aggregateRoot);
            }
            else
            {
                database.Value.As<TAggregateRoot>().Store(aggregateRoot);
            }
        }
    }
}
